package com.djx.asynchronousorchestration.demo01;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.SneakyThrows;
import org.junit.Test;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;

/**
 * @ClassName: ArticleService
 * @Description: TODO
 * @author: 星~
 * @date: 2021/9/17 0017 上午 10:06
 */
@RestController
public class ArticleService {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    /**
     * 没有返回值
     * <p>
     * 不会阻止 当前线程运行
     */
    @Test
    public void test01() throws ExecutionException, InterruptedException {
        System.out.println("方法开始执行。。。");
        CompletableFuture.runAsync(() -> {
            System.out.println("异步线程开始执行");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("执行业务流程。。。");
            System.out.println("异步线程执行结束");
        }, executor).get();

        System.out.println("方法执行结束。。。");
    }

    /**
     * 有返回值
     * future.get() 获取结果会阻塞当前线程，直到异步任务执行结束，才会恢复当前线程执行。
     */
    @SneakyThrows
    @Test
    public void test02() {
        System.out.println("方法开始执行。。。");
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步线程开始执行");
            System.out.println("执行业务流程。。。");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行结束");
            return "ABCDEFGHIJKLMNOPQRSTUVWZYZ";
        }, executor);
        System.out.println("方法执行结束。。。" + future.get());
    }


    /**
     * whenComplete同步执行回调
     *
     * @return
     */
    @SneakyThrows
//    @Test
    @RequestMapping("/test03")
    public Synccc test03() {
        CompletableFuture<Synccc> exceptionally = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步线程开始执行");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步执行线程：" + Thread.currentThread().getName());
            System.out.println("执行业务流程。。。");
            System.out.println("异步线程执行结束");
//            int i = 1 / 0;
            Synccc synccc = new Synccc();
            synccc.setId(1L);
            synccc.setName("24桥");
            return synccc;
        }, executor).whenComplete((synccc, throwable) -> {
            System.out.println("方法返回结果为：" + synccc);
            System.out.println("whenComplete  " + Thread.currentThread().getName());
            System.out.println("异常为" + throwable);
        }).exceptionally(throwable -> {
            if (throwable == null) {
                return null;
            }
            Synccc synccc = new Synccc();
            synccc.setThrowable(throwable);
            return synccc;
        });
        return exceptionally.get();

    }

    @Data
    @JsonInclude(value = JsonInclude.Include.NON_NULL)
    static class Synccc {
        private Long id;
        private String name;
        private Throwable throwable;
    }

    /**
     * whenComplete同步执行回调
     *
     * @return
     */
    @SneakyThrows
//    @Test
    @RequestMapping("/test04")
    public Synccc test04() {
        CompletableFuture<Synccc> exceptionally = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步线程开始执行");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("执行业务流程。。。");
            System.out.println("异步执行线程：" + Thread.currentThread().getName());
            System.out.println("异步线程执行结束");
//            int i = 1 / 0;
            Synccc synccc = new Synccc();
            synccc.setId(1L);
            synccc.setName("24桥");
            return synccc;
        }, executor).whenCompleteAsync((synccc, throwable) -> {
            System.out.println("方法返回结果为：" + synccc);
            System.out.println("whenCompleteAsync " + Thread.currentThread().getName());
            System.out.println("异常 为" + throwable);
        }).exceptionally(throwable -> {
            if (throwable == null) {
                return null;
            }
            Synccc synccc = new Synccc();
            synccc.setThrowable(throwable);
            return synccc;
        });
        return exceptionally.get();

    }

    /**
     * handle()方法也是在主线程中执行的。
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @RequestMapping("/test05")
    public void test05() throws ExecutionException, InterruptedException {
        CompletableFuture<Object> handle = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步线程开始执行");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("执行业务流程。。。");
            System.out.println("异步执行线程：" + Thread.currentThread().getName());
            System.out.println("异步线程执行结束");
            int i = 1 / 0;
            Synccc synccc = new Synccc();
            synccc.setId(1L);
            synccc.setName("24桥");
            return synccc;
        }, executor).handle((result, exception) -> {
            System.out.println("handle执行线程：" + Thread.currentThread().getName());
            Object r = null;
            if (result != null) {
                r = result;
            }
            if (exception != null) {
                r = exception;
            }
            return r;
        });
        System.err.println(handle.get());
    }

    /**
     * 线程串行化
     * 1、thenRunL：不能获取上一步的执行结果
     * 2、thenAcceptAsync：能接受上一步结果，但是无返回值
     * 3、thenApplyAsync：能接受上一步结果，有返回值
     */
    @RequestMapping("/test06")
    public void test06() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果：" + i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了..." + res);
            return "Hello" + res;
        }, executor);
        System.out.println("main......end....." + future.get());

    }



    @RequestMapping("/test07")
    public void test07() throws ExecutionException, InterruptedException {

        final CompletableFuture<Object> objectCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return "异步方法,线程号：" + Thread.currentThread().getId();
        }, executor).thenApplyAsync(new Function<String, Object>() {
            @SneakyThrows
            @Override
            public Object apply(String s) {
                System.out.println("上一步返回结果为：" + s);
                Thread.sleep(3000);
                return s;
            }
        });
//        System.out.println("结果为："+objectCompletableFuture.get());
        System.out.println("我是你大爷");

    }

    @RequestMapping("/test08")
    public void test08() throws ExecutionException, InterruptedException {

        final CompletableFuture<String> future0 = CompletableFuture.supplyAsync(() -> {
            System.out.println("01 开始执行");
            System.out.println("01 线程号为："+Thread.currentThread().getId());
            System.out.println("01 执行结束");
            return "我是任务一";
        }, executor);

        final CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("02 开始执行");
            System.out.println("02 线程号为："+Thread.currentThread().getId());
            System.out.println("02 执行结束");
            int i =10/0;
            return 2;
        }, executor).exceptionally(e -> {
            String message = e.getMessage();
            System.out.println("异常为" + message);
            return 9;
        });

        final CompletableFuture<String> future = future0.thenCombineAsync(future1, (t, u) -> {
            System.out.println("任务一：" + t);
            System.out.println("任务二：" + u);
            System.out.println("03 线程号为："+Thread.currentThread().getId());
            System.out.println("任务一、二执行完毕");
            return t + u;
        }, executor);

        System.out.println("线程运行结果为：" + future.get());
        System.out.println("主 线程号为："+Thread.currentThread().getId());

    }

}
